package com.bestcem.xm.survey.export.type;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.bestcem.xm.survey.export.BaseTypeHandler;
import com.bestcem.xm.survey.grpc.client.dto.QstructsDto;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.util.*;
import java.util.stream.Collectors;

import static com.bestcem.xm.survey.enums.QuestionTypeEnum.QUESTION_TYPE_SCORE;

/**
 * 打分题
 */
@Slf4j
@Component
public class ScoreHandler implements BaseTypeHandler {

    @Override
    public Map<String, String> getSelectColumnChangeDictV2(JSONObject data, String dtype) {
        Map<String, String> column_change_dict = new HashMap();
        String custom_qtype = (String) data.get("custom_qtype");
        if ("nps".equals(custom_qtype)) {
            List<String> v1 = (List<String>) getSelectRealcolV2(data, data.getJSONArray("items").getJSONObject(0), dtype, custom_qtype);
            List<String> v2 = (List<String>) getSelectReadablecolV2(data, data.getJSONArray("items").getJSONObject(0), custom_qtype);
            int min = Math.min(v1.size(), v2.size());
            for (int i = 0; i < min; i++) {
                column_change_dict.put(v1.get(i), v2.get(i));
            }
        } else {
            List<JSONObject> items = (List<JSONObject>) data.getOrDefault("items", Collections.emptyList());
            items.forEach(v -> column_change_dict.put((String) getSelectRealcolV2(data, v, dtype, custom_qtype), (String) getSelectReadablecolV2(data, data, custom_qtype)));
        }
        return column_change_dict;
    }

    private Object getSelectRealcolV2(JSONObject data, JSONObject item, String dtype, String custom_type) {
        if ("nps".equals(custom_type)) {
            if (!"readable".equals(dtype)) {
                return Arrays.asList(String.format("%s__%s", data.get("cid"), item.get("id")), String.format("%s__NPSType", data.get("cid")));
            }
            return Arrays.asList(data.getString("cid"), String.format("%s__NPSType", data.get("cid")));
        }
        return String.format("%s__%s", data.get("cid"), item.get("oid"));
    }

    private Object getSelectReadablecolV2(JSONObject data, JSONObject item, String custom_type) {
        if ("nps".equals(custom_type)) {
            return Arrays.asList(BaseTypeHandler.clearHtml(data.getString("title")), String.format("%s__NPS客户类型", data.get("title")));
        } else if (data.getJSONArray("items").size() == 1) {
            return String.format("%s__分值", BaseTypeHandler.clearHtml(data.getString("title")));
        }
        return String.format("%s__%s", BaseTypeHandler.clearHtml(data.getString("title")), BaseTypeHandler.clearHtml(item.getString("title")));
    }

    @Override
    public Map<String, String> getOpenColumnChangeDictV2(JSONObject data) {
        Map<String, String> res = new HashMap();
        List<JSONObject> items = (List<JSONObject>) data.getOrDefault("items", Collections.emptyList());
        items.forEach(v -> {
            if (isOpenOption(v)) {
                res.put(getOpenRealcolV2(data, v), getOpenReadablecolV2(data, v));
            }
        });
        return res;
    }

    private String getOpenRealcolV2(JSONObject data, JSONObject item) {
        return String.format("%s__%s__open", data.getString("cid"), item.getString("id"));
    }

    private String getOpenReadablecolV2(JSONObject data, JSONObject item) {
        return String.format("%s__%s__开放", BaseTypeHandler.clearHtml(data.getString("title")), BaseTypeHandler.clearHtml(item.getString("title")));
    }

    @Override
    public List<String> getSelectColumnListV2(JSONObject data, String dtype) {
        String custom_qtype = (String) data.get("custom_qtype");
        if ("nps".equals(custom_qtype)) {
            return (List<String>) getSelectRealcolV2(data, data.getJSONArray("items").getJSONObject(0), dtype, custom_qtype);
        }
        List<String> res = new ArrayList();
        data.getJSONArray("items").forEach(v -> res.add((String) getSelectRealcolV2(data, (JSONObject) v, dtype, custom_qtype)));
        return res;
    }

    @Override
    public List<String> getOpenColumnListV2(JSONObject data) {
        List<String> res = new ArrayList();
        List<JSONObject> items = (List<JSONObject>) data.getOrDefault("items", Collections.emptyList());
        items.forEach(v -> {
            if (isOpenOption(v)) {
                res.add(getOpenRealcolV2(data, v));
            }
        });
        return res;
    }


    @Override
    public Map<Object, Object> getSelectAnswerDictV2(JSONObject dataValue, Object answers, String dtype, Boolean score_apply_type) {
        Map<Object, Object> data = new HashMap<>();
        List<JSONObject> items = (List<JSONObject>) dataValue.getOrDefault("items", Collections.emptyList());
        String custom_qtype = dataValue.getString("custom_qtype");
        if (Objects.isNull(answers)) {
            items.forEach(item -> data.put(getSelectRealcolV2(dataValue, item, dtype, custom_qtype), null));
        } else {
            boolean no_apply = (boolean) dataValue.getOrDefault("no_apply", false);
            items.forEach(item -> {
                for (Map.Entry<String, List> entry : ((Map<String, List>) answers).entrySet()) {
                    String gid = entry.getKey();
                    List answer = entry.getValue();
                    if (item.getString("gid").equals(gid)) {
                        if (CollUtil.isNotEmpty(answer)) {
                            try {
                                //渲染类型
                                if ("nps".equals(custom_qtype)) {
                                    if (no_apply && "".equals(answer.get(0))) {
                                        data.put(((List) getSelectRealcolV2(dataValue, item, dtype, custom_qtype)).get(0), score_apply_type ? answer.get(answer.size() - 1) : null);
                                    } else {
                                        data.put(((List) getSelectRealcolV2(dataValue, item, dtype, custom_qtype)).get(0), answer.get(0));
                                    }
                                    data.put(((List) getSelectRealcolV2(dataValue, item, dtype, custom_qtype)).get(1), (no_apply && "".equals(answer.get(0))) ? null : getNpsSelectTypeAnswer((int) answer.get(0)));
                                } else {
                                    if (no_apply && "".equals(answer.get(0))) {
                                        data.put(getSelectRealcolV2(dataValue, item, dtype, custom_qtype), score_apply_type ? answer.get(answer.size() - 1) : null);
                                    } else {
                                        data.put(getSelectRealcolV2(dataValue, item, dtype, custom_qtype), answer.get(0));
                                    }
                                }
                            } catch (Exception e) {
                                if ("nps".equals(custom_qtype)) {
                                    data.put(((List) getSelectRealcolV2(dataValue, item, dtype, custom_qtype)).get(0), null);
                                    data.put(((List) getSelectRealcolV2(dataValue, item, dtype, custom_qtype)).get(1), null);
                                } else {
                                    data.put(getSelectRealcolV2(dataValue, item, dtype, custom_qtype), null);
                                }
                            }
                        } else {
                            if ("nps".equals(custom_qtype)) {
                                data.put(((List) getSelectRealcolV2(dataValue, item, dtype, custom_qtype)).get(0), null);
                                data.put(((List) getSelectRealcolV2(dataValue, item, dtype, custom_qtype)).get(1), null);
                            } else {
                                data.put(getSelectRealcolV2(dataValue, item, dtype, custom_qtype), null);
                            }
                        }
                        break;
                    }
                    if ("nps".equals(custom_qtype)) {
                        data.put(((List) getSelectRealcolV2(dataValue, item, dtype, custom_qtype)).get(0), null);
                        data.put(((List) getSelectRealcolV2(dataValue, item, dtype, custom_qtype)).get(1), null);
                    } else {
                        data.put(getSelectRealcolV2(dataValue, item, dtype, custom_qtype), null);
                    }
                }
            });
        }
        return data;
    }

    public String getNpsSelectTypeAnswer(int score) {
        if (score <= 6) {
            return "贬低者";
        }
        if (score <= 8) {
            return "中立者";
        }
        if (score <= 10) {
            return "推荐者";
        }
        return null;
    }

    @Override
    public Map<Object, Object> getOpenAnswerDictV2(JSONObject dataValue, Object answerValue) {
        Map<Object, Object> data = new HashMap<>();
        List<JSONObject> items = (List<JSONObject>) dataValue.getOrDefault("items", Collections.emptyList());
        if (Objects.isNull(answerValue)) {
            items.forEach(item -> {
                if (isOpenOption(item)) {
                    data.put(getOpenRealcolV2(dataValue, item), null);
                }
            });
        } else {
            Map<String, Object> answers = (Map<String, Object>) answerValue;
            items.forEach(item -> {
                for (Map.Entry<String, Object> entry : answers.entrySet()) {
                    String gid = entry.getKey();
                    Object answer = entry.getValue();
                    if (gid.equals(item.getString("gid"))) {
                        if (isOpenOption(item)) {
                            if (((List) answer).size() > 1) {
                                data.put(getOpenRealcolV2(dataValue, item), BaseTypeHandler.clearHtml((String) ((List) answer).get(1)));
                            }
                        } else {
                            data.put(getOpenRealcolV2(dataValue, item), null);
                        }
                    }
                }
            });
        }
        return data;
    }

    @Override
    public List<List<String>> getVarLabelsV2(JSONObject dataValue, boolean not01, boolean need_title) {
        List<List<String>> data = new ArrayList<>();
        List<String> var_list = new ArrayList(), val_list = new ArrayList(), head_list = new ArrayList();
        List<JSONObject> items = (List<JSONObject>) dataValue.getOrDefault("items", Collections.emptyList());
        String custom_qtype = dataValue.getString("custom_qtype");
        //打分题 和 游标打分题
        if ("star_score".equals(custom_qtype) || "cursor_score".equals(custom_qtype)) {
            if (items.size() == 1) {
                JSONObject item = items.get(0);
                var_list.add(String.format("VARIABLE LABELS %s__%s '%s:分值'.", dataValue.get("cid"), item.get("oid"), getTitles(dataValue, null, item, false)));
                head_list.add(String.format("%s__%s", dataValue.get("cid"), item.get("oid")));
            } else {
                items.forEach(item -> {
                    var_list.add(String.format("VARIABLE LABELS %s__%s '%s'.", dataValue.get("cid"), item.get("oid"), getTitles(dataValue, null, item, false)));
                    head_list.add(String.format("%s__%s", dataValue.get("cid"), item.get("oid")));
                });
            }
            if ("star_score".equals(custom_qtype)) {
                getStarScoreVal(dataValue, head_list, val_list);
            } else {
                getCursorScoreVal(dataValue, head_list, val_list);
            }
            //nps题
        } else if ("nps".equals(custom_qtype)) {
            JSONObject item = items.get(0);
            var_list.add(String.format("VARIABLE LABELS %s__%s '%s':分值'.", dataValue.get("cid"), item.get("oid"), getTitles(dataValue, null, item, false)));
            var_list.add(String.format("VARIABLE LABELS %s__NPSType '%s:客户类型'.", dataValue.get("cid"), getTitles(dataValue, null, item, false)));
            head_list.add(String.format("%s__%s", dataValue.get("cid"), item.get("oid")));
            getNpsVal(dataValue, head_list, val_list);
        }
        data.add(var_list);
        data.add(val_list);
        return data;
    }

    private void getNpsVal(JSONObject dataValue, List<String> head_list, List<String> val_list) {
        String s = String.format("ADD VALUE LABELS %s", StrUtil.join(" ", head_list));
        List<String> data_list = BaseTypeHandler.convertString(s, 250);
        val_list.addAll(data_list);
        JSONObject question = dataValue.getJSONObject("question");
        List<Integer> score = (List<Integer>) question.get("score_range");
        int big_score = score.get(score.size() - 1);
        for (int i = 0; i < big_score + 1; i++) {
            //左边文字、右边文字分别对照最小分值&最大分值；如果未设置左边/右边文字，对应位置直接显示分值即可；分值由低到高显示
            if (i == 0) {
                //最低分
                Object left_words = getLeftRightWords(question, i, "left_words");
                val_list.add(String.format("    %s '%s'%s", i, left_words, i == big_score ? "" : "."));
            } else if (i == big_score) {
                //最高分
                Object right_words = getLeftRightWords(question, i, "right_words");
                val_list.add(String.format("    %s '%s'%s", i, right_words, i == big_score ? "" : "."));
            } else {
                val_list.add(String.format("    %s '%s'%s", i, i, i == big_score));
            }
        }
    }

    private void getCursorScoreVal(JSONObject dataValue, List<String> head_list, List<String> val_list) {
        String s = String.format("ADD VALUE LABELS %s", StrUtil.join(" ", head_list));
        List<String> data_list = BaseTypeHandler.convertString(s, 250);
        val_list.addAll(data_list);
        //获取分数范围
        JSONObject question = dataValue.getJSONObject("question");
        List<Integer> score = (List<Integer>) question.get("score_range");
        int scoreLength = score.size();
        for (int i = 0; i < scoreLength; i++) {
            //左边文字、右边文字分别对照最小分值 & 最大分值；如果未设置左边 / 右边文字，对应位置直接显示分值即可；分值由低到高显示
            if (i == 0) {
                //最低分
                Object left_words = getLeftRightWords(question, i, "left_words");
                val_list.add(String.format("    %s '%s'%s", i, left_words, scoreLength == i + 1 ? "" : "."));
            } else {
                //最高分
                Object right_words = getLeftRightWords(question, i, "right_words");
                val_list.add(String.format("    %s '%s'%s", i, right_words, scoreLength == i + 1 ? "" : "."));
            }
        }
    }

    private void getStarScoreVal(JSONObject dataValue, List<String> head_list, List<String> val_list) {
        String s = String.format("ADD VALUE LABELS %s", StrUtil.join(" ", head_list));
        List<String> data_list = BaseTypeHandler.convertString(s, 250);
        val_list.addAll(data_list);
        //获取分数范围
        JSONObject question = dataValue.getJSONObject("question");
        List<Integer> score = (List<Integer>) question.get("score_range");
        Integer min_score = score.get(0);
        Integer max_score = score.get(score.size() - 1);
        if (ObjectUtil.isNotEmpty(question.get("moreTextEffect"))) {
            //若分值未设置对应的提示文字，英文引号内直接显示分值即可；若有需显示对应提示文字；分值由低到高显示
            List<JSONObject> tipList = (List<JSONObject>) question.get("tipList");
            if (CollUtil.isNotEmpty(tipList)) {
                Integer length = tipList.size();
                for (int i = 0; i < length; i++) {
                    JSONObject item = tipList.get(i);
                    String content = item.getString("content");
                    if (StrUtil.isEmpty(content)) {
                        content = item.getString("score");
                    }
                    val_list.add(String.format("    %s '%s'%s", item.getString("score"), content, length.equals(i + 1) ? "" : "."));
                }
            } else {
                for (int i = min_score; i < max_score + 1; i++) {
                    val_list.add(String.format("    %s '%s'%s", i, i, max_score.equals(i) ? "" : "."));
                }
            }
        } else {
            for (int i = min_score; i < max_score + 1; i++) {
                if (min_score.equals(i)) {
                    //第一个选项如果左边文字有值，显示左边文字，否则显示分数
                    Object left_words = getLeftRightWords(question, i, "left_words");
                    val_list.add(String.format("    %s '%s'%s", i, left_words, max_score.equals(i) ? "" : "."));
                } else if (max_score.equals(i)) {
                    //第一个选项如果左边文字有值，显示左边文字，否则显示分数
                    Object right_words = getLeftRightWords(question, i, "left_words");
                    val_list.add(String.format("    %s '%s'%s", i, right_words, max_score.equals(i) ? "" : "."));
                } else {
                    val_list.add(String.format("    %s '%s'%s", i, i, max_score.equals(i) ? "" : "."));
                }
            }
        }
    }

    private Object getLeftRightWords(JSONObject question, int item, String word) {
        Object value = question.getJSONObject("prompt_text").get(word);
        if (ObjectUtil.isNotEmpty(value)) {
            return value;
        }
        return item;
    }

    @Override
    public List<String> getSpssCodeV2(JSONObject param, QstructsDto qstruct) {
        List<JSONObject> items = (List<JSONObject>) param.getOrDefault("items", Collections.emptyList());
        List<String> head_list = items.stream().map(item -> String.format("%s__%s", param.get("cid"), item.get("oid"))).collect(Collectors.toList());
        List<String> head_list_open = items.stream().filter(item -> Objects.nonNull(item.getBoolean("is_open")) && item.getBoolean("is_open")).map(item -> String.format("%s__%s__open", param.get("cid"), item.get("oid"))).collect(Collectors.toList());
        head_list.addAll(head_list_open);
        if ("nps".equals(param.getString("custom_qtype"))) {
            head_list.add(String.format("%s__NPSType", param.get("cid")));
        }
        return head_list;
    }

    @Override
    public String getQuestionTypeValue() {
        return QUESTION_TYPE_SCORE.getValue();
    }
}
